Segmentation fault, adresowanie, tablice
Oglądasz archiwalną wersję wątku "Segmentation fault, adresowanie, tablice" z forum alt.pl.asm
Damian Sobota
Hej!

Zaczalem wlasnie programowac w assemblerze (kompilator NASM/Linux). Ucze
sie z kursu Bogdana (bogdro). Niestety juz na samym poczatku natrafilem
na problemy. Czy ktos moglby mi wytlumaczyc, dlaczego taki kod wykonuje
sie poprawnie:

<code

; program kopiuje do cx drugi element tablicy tab

section .text
         global _start

tab     times   12      dw      0bbh

_start:

         mov     cx,[tab+2]
         mov     eax,1
         int     80h

</code

a przy wykonywaniu takiego otrzymuje "Segmentation fault":

<code

;program kopiuje do drugiego elementu tablicy tab wartosc 0FFh

section .text
         global _start

tab     times   12      dw      0bbh

_start:

         mov     cx,0ffh
         mov     [tab+2],cx
         mov     eax,1
         int     80h

</code

?

Co jest zle w powyzszym (drugim) kodzie?

**********

W drugiej lekcji tego kursu znajduje takie oto zadanie:

<quote
Zadeklaruj tablicę 12 słów (16-bitowych) o wartości BB (szestnastkowo),
po czym do każdego z tych słów wpisz wartość FF szestnastkowo (bez
żadnych pętli).
</quote

Nasuwa mi sie wobec tego pytanie. Czy majac tablice zdefiniowana tak:

tab     times   12      dw      0bbh

moge ja nadpisac wartosciami 0ffh za pomoca jednej instrukcji? Wydaje mi
sie ze da sie to zrobic trzema wykonaniami instrukcji mov, wystarczy
tylko ze w odpowiednie miejsce w tablicy tab (pola: tab[0], tab[4],
tab[8]) wpisze wartosci typu dq. Mam racje? Przecież w tym momencie
tablica tab w pamieci ma postac:

BB00BB00BB00BB00BB00BB00BB00BB00BB00BB00BB00BB00

a odpowiednia wartosc typu dq mialaby postac:

FF00FF00FF00F00.

Da sie tak zrobic? Za pomoca mov? Moglby ktos mi to pokazac?

Licze na Wasze odpowiedzi!

Bernard

Hej!

Zaczalem wlasnie programowac w assemblerze (kompilator NASM/Linux). Ucze
sie z kursu Bogdana (bogdro). Niestety juz na samym poczatku natrafilem


He, he, he...

na problemy. Czy ktos moglby mi wytlumaczyc, dlaczego taki kod wykonuje
sie poprawnie:

<code
(...)
</code

a przy wykonywaniu takiego otrzymuje "Segmentation fault":

<code

;program kopiuje do drugiego elementu tablicy tab wartosc 0FFh

section .text
        global _start

tab     times   12      dw      0bbh


"tab" jest w sekcji kodu, a więc jest chroniona przed zapisem. To
wystarczy. Jak coś ma być daną, to zadeklaruj to w sekcji danych.

_start:

        mov     cx,0ffh
        mov     [tab+2],cx


O właśnie na tej instrukcji powyżej wylatuje Twój kod.
        mov     eax,1
        int     80h

</code


Damian Sobota

"tab" jest w sekcji kodu, a więc jest chroniona przed zapisem. To
wystarczy. Jak coś ma być daną, to zadeklaruj to w sekcji danych.


No OK. Zdefiniowalem to w section .data i teraz poszlo bez Segmentation
fault. Dzieki!

Hmmm... A moglbys odpowiedziec na moje drugie pytanie? Bylbym bardzo
wdzieczny :).

Bogdan (bogdro)

Hej!


  Na pierwsze pytanie już znasz odpowiedź, więc dodam tylko parę słów.
Oczywiście, gratuluję systemu (jakie distro?), i sam też używam NASMa.
  Cieszę się też, że eksperymentujesz samodzielnie wykonując zadania.
Nie musisz się bać o zawieszenie systemu :)

[...]

W drugiej lekcji tego kursu znajduje takie oto zadanie:

<quote
Zadeklaruj tablicę 12 słów (16-bitowych) o wartości BB (szestnastkowo),
po czym do każdego z tych słów wpisz wartość FF szestnastkowo (bez
żadnych pętli).
</quote

Nasuwa mi sie wobec tego pytanie. Czy majac tablice zdefiniowana tak:

tab     times   12      dw      0bbh

moge ja nadpisac wartosciami 0ffh za pomoca jednej instrukcji? Wydaje mi
sie ze da sie to zrobic trzema wykonaniami instrukcji mov, wystarczy
tylko ze w odpowiednie miejsce w tablicy tab (pola: tab[0], tab[4],
tab[8]) wpisze wartosci typu dq. Mam racje? Przecież w tym momencie
tablica tab w pamieci ma postac:

BB00BB00BB00BB00BB00BB00BB00BB00BB00BB00BB00BB00

a odpowiednia wartosc typu dq mialaby postac:

FF00FF00FF00F00.

Da sie tak zrobic? Za pomoca mov? Moglby ktos mi to pokazac?

Licze na Wasze odpowiedzi!


  To jest dopiero druga część kursu, więc nie przesadzajmy. Nigdzie nie

było zrobione np. w 12 instrukcjach MOV. Chodzi o to, aby sobie
poćwiczyć adresowanie.

  Ale pytanie postawiłeś, więc odpowiem. 24 bajty można przenieść naraz
- np. instrukcją REP MOVSB. Oczywiście, wymaga to kilku instrukcji
przygotowawczych. Więc w dokładnie jednej instrucji się nie da, a
przyczyna jest dość prosta: żaden rejestr nie jest wystarczjąco pojemny.
Największe rejestry są 16-bajtowe. Można więc użyć jednego takiego i
jednego ośmiobajtowego. Więcej w częsci 6. kursu.

Damian Sobota

 Na pierwsze pytanie już znasz odpowiedź, więc dodam tylko parę słów.
Oczywiście, gratuluję systemu (jakie distro?), i sam też używam NASMa.


Distro Mandrake, w tym miesiacu jednak przerzucam sie na Debiana (niby
Mandrake to Linux, ale jednak momentami czuje sie dalej jak w Windowsie
- wszystko na tacy, praktycznie zadnego szukania, jedynie instalacja
Neostrady wymagala ode mnie troche wysilku, gdyz okazalo sie, ze modem
Thompson SpeedTouch 330 wystepuje w dwoch wersjach, o czym nie wspomina
sie prawie nigdzie, a kazda z tych wersji wymaga innego mikrokodu :)).

 Cieszę się też, że eksperymentujesz samodzielnie wykonując zadania. Nie
musisz się bać o zawieszenie systemu :)


Nie boje :).

 To jest dopiero druga część kursu, więc nie przesadzajmy. Nigdzie nie

było zrobione np. w 12 instrukcjach MOV. Chodzi o to, aby sobie
poćwiczyć adresowanie.


Uff... A juz sie balem, ze czegos nie zrozumialem. Moglbys jedynie
dopisac o tej "section .data", bo (co prawda gdzies o tym wspomniales,
ale jakby marginalnie) trudno sie kapnac, ze to o to chodzi.

[ciach odpowiedz] Więcej w częsci 6. kursu.


Okej. Dzieki za odpowiedz. Przystepuje do dalszej lektury.

Damian Sobota

 [ciacho]

Mam jeszcze jedno pytanie odnosnie adresowania. Mianowicie, dlaczego
taki kod dziala bez problemu:

         mov     cx,0ffh
         lea     ebx,[tab]
         mov     esi,12
         imul    esi,5
         mov     word [ebx+esi+3],cx

a w czasie kompilacji takiego otrzymuje blad "invalid effective address"
(w ostatniej linii):

         mov     cx,0ffh
         lea     ebx,[tab]
         mov     esi,12
         mov     word [ebx+esi*5+3],cx

!?

Przeciez tu nie ma zadnej roznicy. Chyba...

Bernard


 [ciacho]

Mam jeszcze jedno pytanie odnosnie adresowania. Mianowicie, dlaczego
taki kod dziala bez problemu:

        mov     cx,0ffh
        lea     ebx,[tab]
        mov     esi,12
        imul    esi,5
        mov     word [ebx+esi+3],cx

a w czasie kompilacji takiego otrzymuje blad "invalid effective address"
(w ostatniej linii):

        mov     cx,0ffh
        lea     ebx,[tab]
        mov     esi,12
        mov     word [ebx+esi*5+3],cx

!?

Przeciez tu nie ma zadnej roznicy. Chyba...


Jest jedna drobna różnica.
Tryb adresowania [ebx+esi+3] w x86 istnieje, a tryb [ebx+esi*5+3] nie
istnieje.

Nie rozumiem dlaczego mnożysz esi przez 5. Jeśli to ma być rozwiązanie
tego "zadania", to wypadałoby mnożyć przez długość zapisywanej danej.

Poza tym asembler wcale się nie obrazi, jeśli napiszesz [esi+tab+3],
zamiast pakować wcześniej adres tab do ebx. Nie obrazi się również na
zapis "mov ebx, tab" - działa tak samo jak "lea ebx,[tab]" ale kod
generuje krótszy.

Damian Sobota

Jest jedna drobna różnica.
Tryb adresowania [ebx+esi+3] w x86 istnieje, a tryb [ebx+esi*5+3] nie
istnieje.



w x86?

Nie rozumiem dlaczego mnożysz esi przez 5. Jeśli to ma być rozwiązanie
tego "zadania", to wypadałoby mnożyć przez długość zapisywanej danej.


Mnoze, poniewaz tablica tab jest dwuwymiarowa (13 wierszy po 5
elementow), a ja mialem sie odniesc do komorki [12][3] (liczac od zera)/

Poza tym asembler wcale się nie obrazi, jeśli napiszesz [esi+tab+3],
zamiast pakować wcześniej adres tab do ebx. Nie obrazi się również na
zapis "mov ebx, tab" - działa tak samo jak "lea ebx,[tab]" ale kod
generuje krótszy.


Dobrze wiedziec.

Bernard


| Jest jedna drobna różnica.
| Tryb adresowania [ebx+esi+3] w x86 istnieje, a tryb [ebx+esi*5+3] nie
| istnieje.

w x86?


Mogę, ale po co. Lepiej, jeśli przeczytasz pierwszą (a potem drugą)
część IA-32 Programmer's Reference Manual, do ściągnięcia z
developer.intel.com.

| Nie rozumiem dlaczego mnożysz esi przez 5. Jeśli to ma być rozwiązanie
| tego "zadania", to wypadałoby mnożyć przez długość zapisywanej danej.

Mnoze, poniewaz tablica tab jest dwuwymiarowa (13 wierszy po 5
elementow), a ja mialem sie odniesc do komorki [12][3] (liczac od zera)/


Jeśli masz się dostać tylko do tego jednego elementu, to napisz

mov [tablica + 12 * długość_wiersza*rozmiar_elementu +
3*rozmiar_elementu], wartość

Bogdan (bogdro)


| Jest jedna drobna różnica.
| Tryb adresowania [ebx+esi+3] w x86 istnieje, a tryb [ebx+esi*5+3] nie
| istnieje.

w x86?


[...]

adresowania (dla Linuksa tylko jeden - 32-bitowy). Popatrz na parametr
"skala"/"mnożnik". Tego właśnie używasz.
  Zaraz spróbuję się zabrać za dorobienie info o sekcji danych.

P.S. Ja teraz używam Fedory 4. Zainstalowałem w piątek, więc jeszcze
świeża :) Wcześniej też miałem Mdk, ale soft już był stary.

Damian Sobota


adresowania (dla Linuksa tylko jeden - 32-bitowy). Popatrz na parametr
"skala"/"mnożnik". Tego właśnie używasz.


Aaaaa... Nie doczytalem tego:

<quote
# mnożnik (scale) = 1, 2, 4 lub 8 (gdy nie jest podany, przyjmuje się 1)
</quote

A to wlasciwie wszystko wyjasnia, bo dla tych liczb mnozenie dziala.

P.S. Ja teraz używam Fedory 4. Zainstalowałem w piątek, więc jeszcze
świeża :) Wcześniej też miałem Mdk, ale soft już był stary.


No wlasnie sa problemy z instalowaniem nowego softu, gdyz praktycznie
caly czas musze kompilowac kody zrodlowe, bo dla mojej wersji (10.0) nie
ma odpowiednich pakietow. A przy okazji zawsze wyskakuja bledy o
brakujacych bibliotek :\.

A jak wrazenia z Fedory 4?!

Bogdan (bogdro)

[...]

No wlasnie sa problemy z instalowaniem nowego softu, gdyz praktycznie
caly czas musze kompilowac kody zrodlowe, bo dla mojej wersji (10.0) nie
ma odpowiednich pakietow. A przy okazji zawsze wyskakuja bledy o
brakujacych bibliotek :\.


  Skonfiguruj urpmi i zasysaj pakiety z sieci. Zależności zostaną
automatycznie doinstalowane. Skorzystaj z http://easyurpmi.zarb.org/ -
samo ci powie, jakie komendy trzeba wydać. Instalator graficzny z resztą
też to chyba potrafił.
  Gorzej jest, gdy coraz więcej programów wymaga nowszego glibc. Wtedy
przesiadłem się z Mdk 9.0 na Mdk 9.2.

A jak wrazenia z Fedory 4?!


  Coraz lepsze. Drukarka, dźwięk działa (choć XMMS do bani, tak samo jak
w Auroksie 10.1). Skonfigurowałem YUM i instaluję pakiety z sieci (tak
jak URPMI w mdk). KDE 3.4 nawet ładne (choć w domyślnym motywie wygląda
jak GNOME), już skonfigurowane. Firefox, Thunderbird też. Tylko konsola
szwankuje, bo lewe brzegi liter są wyświetlane z prawej strony ekranu i
raczej nie jest to wina monitora. Na razie nie narzekam, bo wcześniej
tło było ... różowe.
  Jeszcze język musiałem ustawić, bo przynajmniej FC i Aurox jako
domyślne kodowanie przyjmują sobie UTF-8 i wszystko szlag trafia.
  Ale jakoś idzie. Do bani trochę jest instalator pakietów (graficzny),
bo nie pokazuje zależności ani przy instalowaniu, ani przy usuwaniu
pakietów. Teraz już go prawie nie używam. Ten w Mdk był fajny pod tym
względem. Można też było źródła w internecie dodać i się ściągało
automatycznie.
  Centrum Sterowania w Mdk tutaj jest w postaci podmenu.
  Autologowanie do iksów też musiałem ręcznie wklepać niestety.
  Oczywiście caly soft nowiuśki, czasem nawet za bardzo. libstdc++ mam
za nowe i niektóre programy nie chcę się uruchamiać (rar, firefox/tb
ściągany z neta, RealPlayer).
  Wszystkie serwery już raczej też skonfigurowane.
  Pracuję jeszcze nad grami :)
  Przynajmniej KWrite ani Centrum Sterowania KDE już mi się nie sypie.
  Jest to (oczywiście) dystrybucja redhatopodobna, więc nie miałem
większych kłopotów ze znalezieniem plików konfiguracyjnych.
  Tylko strasznie dbają o to, żeby cały soft był "wolny". Więc na
standardowych płytkach nie znajdziesz np. niczego związanego z MP3 (XMMS).
  Jeśli widziałeś kiedyś Auroksa (który opiera się na FC), to system
wygląda podobnie.

  Jak widać są wady, ale raczej jestem zadowolony.

Remek
Witam!

Z zainteresowaniem śledzę ten wątek. Mnie też się
przyda uzupełnienie wiedzy, ale czegoś nie zrozumiałem.

Największe rejestry są 16-bajtowe


Czy chodzi o rejestry procesora?

Jest jedna drobna różnica. Tryb adresowania


[ebx+esi+3] w x86 istnieje

Czy chodzi o różnicę w składni akceptowanej przez
dany translator, czy o dostępne instrukcje procesora?

Pozdrawiam!

Bogdan (bogdro)

Witam!

Z zainteresowaniem śledzę ten wątek. Mnie też się
przyda uzupełnienie wiedzy, ale czegoś nie zrozumiałem.

| Największe rejestry są 16-bajtowe

Czy chodzi o rejestry procesora?


  Tak, ale tylko jeśli masz Pentium III lub nowszy. Chodzi mi o
128-bitowe rejestry SSE, nazwane xmm*. Można ich użyć do przenoszenia
danych i tylko dlatego o nich wspomniałem (tematem wątku jest
wypełnianie tablicy).

| Jest jedna drobna różnica. Tryb adresowania

[ebx+esi+3] w x86 istnieje

Czy chodzi o różnicę w składni akceptowanej przez
dany translator, czy o dostępne instrukcje procesora?


  O dostępne instrukcje procesora. Nie ma takiego trybu adresowania, w
którym rejestr indeksowy mnoży się przez 5.

może mi ktoś szybko napisac jaki jest adres pop3 dla adresów@op.pl
Czy allegro zawiesza konta licytujące z adresów proxy ?
Wejście na serwer spoza puli adresów IP
  • grobelny pleszew
  • regeneracja prosba do ba
  • Jei9B6li jednak te strony
  • ile wyrabia sie dowod osobisty
  • mroi9BFek biblioteka internetowa
  • desarrollo
  • portos;rolety
  • Modelowanie i sterowanie mobilnych roboti9F3w
  • ghr 15v s
  • Zbieranina wiadomości z for dyskusyjnych : Start